<?php
/*pc端客服*/
namespace app\wechat\controller;

use app\api\model\ChatMsg;
use app\api\model\Client;
use app\api\model\KfReply;
use app\api\model\Users;
use app\api\model\WxUser;
use plugin\filter;
use plugin\Gateway;
use plugin\wx\WXBizDataCrypt;
use plugin\wx\wxHelper;
use think\Session;

class Index extends Common
{
    public function _initialize()
    {
        parent::_initialize();
    }

    //首页接口
    public function index()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }
        //关闭同个浏览器多个对话页面的客户端链接
        $this->closeSameClient();
        //[登陆者是客服，则获取用户列表，反之则相反]
        $client_List = !$this->isKf($this->getCurrentUserid(true)) ? $this->GetKfList() : $this->GetUserList();
        return ['error'=>0,"msg"=>$client_List];
    }

    //客服不在线时，进行发送该信息
    public function sendKfOffLineText($client_id)
    {
        $KfReplyModel = new KfReply();
        $reply = json_encode($KfReplyModel->total(['pageLimit'=>7]),JSON_UNESCAPED_UNICODE);
        if(empty($reply)) return;
        //发送7条记录
        $input = [
            'to_client_id' => $client_id,
            'type'  => 'OffLineText',
            'msg'   => $reply
        ];
        $userModel  = new Client($this->modelDefaultParam());
        $userModel->send_text($input);
    }

    //获取客服列表
    private function GetKfList()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        //当前登陆者是用户，则获取客服列表
        $client = new Client($this->modelDefaultParam());
        $KfModel = new \app\api\model\Kf($this->modelDefaultParam());
        //获取所有在线的客户端id
        $allKfClientId = $client->getAllOnLineClientId();
        //获取所有客服列表
        $list = $KfModel->getAllKf($allKfClientId);
        return $list;
    }

    //获取用户列表
    private function GetUserList()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        $client = new Client($this->modelDefaultParam());
        $userModel = new Users($this->modelDefaultParam());
        //获取所有在线的客户端id
        $allKfClientId = $client->getAllOnLineClientId();
        //获取所有用户
        $list = $userModel->getAllOnLineUser($allKfClientId);
        return $list;
    }

    //聊天页接口
    public function chat()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        //获取聊天对象客户端id
        $post       = postJsonToArray();
        $pid                = $post['pid'];
        //检查聊天对象正确性
        if(!$this->chkCurrentTarget($pid)) return ['error'=>1,'msg'=>"不能与自己聊天哦"];

        //获取聊天对象的客户端信息
        $users = $this->getUserMsg($pid);
        if(empty($users)) return['error'=>1,'msg'=>"聊天对象不存在"];
        //如果当前用户不是客服 并且聊天对象不是客服
        if($users['is_kf'] != 1 && !$this->isKf($this->getCurrentUserid(true))) return ['error'=>1,'msg'=>"请选择客服进行对话哦"];

        return ['error'=>0,'msg'=>$users];
    }


    //获取一个用户信息以及初始化在线离线
    protected function getUserMsg($client_id)
    {

        //获取客户端基本消息
        $userModel  = new Users($this->modelDefaultParam());
        $users      = $userModel->user_info(['enc_client_id'=>$client_id]);
        if(empty($users)) return null;
        //获取未查看历史记录
        $chatMsg = new ChatMsg();
        $users['no_skim'] = $chatMsg->getOneNoSkimLog($client_id,$this->getCurrentUserid(true));
        //user_id加密
        $users['client_id'] = $this->EncUserid($users['client_id']);
        //判断是否在线
        $users['lineState'] = $this->clientOnLine($users['client_id']) ? "在线" : "离线";
        $users['lineStateNum'] = $this->clientOnLine($users['client_id']) ? 1 : 0;

        return $users;
    }


    //判断一个客户端在线
    protected function clientOnLine($client_id)
    {
        $clientModel = new Client($this->modelDefaultParam());
        //在线状态，返回true，否则返回false
        return !empty($clientModel->getClientIdByUid($client_id));
    }

    //检测当前聊天对象
    protected function chkCurrentTarget($pid)
    {
        return !empty($pid) &&  $pid != $this->getCurrentUserid(true);
    }


    //关闭同一个浏览器多个客服端页面
    protected function closeSameClient()
    {
        $clientModel = new Client($this->modelDefaultParam());
        //关闭同个浏览器另外一个聊天室链接
        $usermsg = $clientModel->getClientIdByUid($this->getCurrentUserid(true));
        if(!empty($usermsg))
        {
            $clientModel->closeClient($usermsg[0]);
        }
    }

    //绑定用户
    public function bind_user()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }
        /**
         * 参数说明
         * post client_id 客户端id
         */
        $post       = postJsonToArray();

        $client_id  = $post['client_id'];

        $UserModel  = new Client($this->modelDefaultParam());
        //关闭之前的链接
        $client = $UserModel->getClientIdByUid();
        if(!empty($client) && isset($client[0]))
        {
            $UserModel->closeClient($client[0]);
        }

        $result     = $UserModel->bind_user($client_id);
        //通知所有人该用户上线
        $this->clientOn($result['client_id']);
        return $result;
    }

    //给用户发送消息
    public function send_text()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }
        /**
         * 参数说明
         * post type text 为文本消息 photo 为图片消息
         * post type msg 对应消息类型的内容
         * post to_client_id 对方的enc_client_id
         * post f_client_id  enc_client_id
         * post token
         * return {error,msg}
         */
        $post       = ArrRemoveJs(postJsonToArray());
        //数据验证
        if(!isset($post['f_client_id'])
            || !isset($post['to_client_id'])
        )
        {
            return ['error'=>1,'error'=>'错误'];
        }


        $clientModel  = new Client($this->modelDefaultParam());
        $result     = $clientModel->send_text($post);

        //检查对方是否在线
        $userModel = new Users();
        $toUserInfo = $userModel->user_info(['enc_client_id'=>$post['to_client_id']]);
        if($toUserInfo['is_kf'] == 1 && !$this->clientOnLine($post['to_client_id']))
        {
            //给当前回复查看问题
            $this->keywordAutoReply(['f_client_id'=>$post['f_client_id'],'to_client_id'=>$post['to_client_id'],'keyword'=>$post['msg']]);
            //给当前发送人发送离线推送
            $this->sendKfOffLineText($post['f_client_id']);
        }

        return $result;
    }

    public function send_photo()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        $post = postJsonToArray();

        //数据验证
        if(!isset($post['f_client_id'])
            || !isset($post['to_client_id'])
        )
        {
            return ['error'=>1,'error'=>'错误'];
        }

        // 获取表单上传文件
        $file = request()->file('photo');
        $path =  'public' . DS . 'uploads'. DS . "chat_msg";
        if(empty($file)) return json_encode(['error'=>1,'msg'=>'没有上传图片'],JSON_UNESCAPED_UNICODE);
        $info = $file->validate(['size'=>2097152,'ext'=>'jpg,png,gif'])->move(ROOT_PATH . $path);
        if($info){
            // 成功上传后 获取上传信息
            // 输出 jpg
            $img_path = str_replace('\\','/',$path.DS.$info->getSaveName());
            $post['type'] = 'photo';
            $post['msg']  = $this->config('domain')."/".$img_path;
            //客户端发送
            $userModel  = new Client($this->modelDefaultParam());
            $result     = $userModel->send_text($post);
            return json_encode($result,JSON_UNESCAPED_UNICODE);

        }else{
            return json_encode([
                'error' => 1,
                'msg'   => $file->getError()
            ],JSON_UNESCAPED_UNICODE);
        }

    }

    //获取最近的聊天记录
    public function getLateMsg()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }
        /**
         * 参数说明
         * post to_client_id        当前对话的enc_client_id
         * post f_client_id  操作者enc_client_id
         * post token       token令牌
         * post msgid  最早对话的msgid，获取比这个消息id更小的id即更早的消息记录
         *
         */
        $post = postJsonToArray();
        //token验证
        if(!isset($post['f_client_id'])
            || !isset($post['token'])
            || !$this->chkToken(['enc_client_id'=>$post['f_client_id'],'token'=>$post['token']])
            || !$this->clientOnLine($post['f_client_id'])
        )
        {
            return ['error'=>1,'token'=>'错误'];
        }
        $MsgModel = new ChatMsg($this->modelDefaultParam());
        $log = $MsgModel->getlog($this->getCurrentUserid(true),$post['to_client_id'],$post['msgid']);
        //客户端给当前用户发送历史消息
        $clientModel = new Client($this->modelDefaultParam());
        $clientModel->sendOneUser(['type'=>'history','msg'=>$log,'client_id'=>$post['f_client_id']],$this->getCurrentUserid(true));
    }


    //获取最近聊天的用户列表
    public function getLateUser()
    {
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        /**
         * 参数说明
         * post.f_client_id  对方的client_id 即数据库中的enc_client_id
         * post.token       [如果client_id是客服账号，则无需该参数]当前用户请求的合法token
         */
        $input = postJsonToArray();
        //验证参数以及该用户是否在线状态
        if(
            !isset($input['f_client_id'])
            || !isset($input['token'])
            || !$this->clientOnLine($input['f_client_id'])
        )
        {
            return ['error'=>'1','msg'=>"非法操作"];
        }

        $msgModel = new ChatMsg();
        $userModel = new Users();
        $clientModel= new Client();

        //获取用户
        if(!$info = $userModel->user_info(['enc_client_id'=>$input['f_client_id']])){ return ['error'=>1,'非法操作']; };
        //检查token，并加载数据
        if($this->chkToken(['token'=>$input['token'],'enc_client_id'=>$input['f_client_id']]))
        {
            //发联系列表通过soket发送
            $data = $msgModel->getLogUser($input['f_client_id']);
            $clientModel->sendOneUser(['type'=>'userList','msg'=>['data'=>$data,'is_kf'=>1]],$input['f_client_id']);
        }
        else
        {
            return ['error'=>1,'非法操作'];
        }

    }

    //小程序登录认证
    public function doauth()
    {
        /**
         * 参数说明
         * post.wcx_session session验证
         * post.encryptedData
         * post.iv
         * post.rawData
         * post.signature
         * post.code
         */

        $post = postJsonToArray();
        $post['encryptedData'] = urldecode($post['encryptedData']);
        $postParam = [
            'encryptedData' => "",'iv'=>"","rawData"=>"","signature"=>"","code"=>""
        ];
        $post = array_merge($postParam,$post);
        //循环验证
        foreach($postParam as $k=>$v)
        {
            if(empty($post[$k]))
            {
                $file = fopen('small_login.txt',"w");
                fwrite($file,"缺少参数");
                fclose($file);
                return ['error'=>1,"msg"=>"缺少参数"];
                die;
            }
        }

        //根据code获取session_key
        if(!$session_key = $this->getSessionKey($post['code']))
        {

            return ['error'=>1,"msg"=>"code参数错误"];

        }

        //验证签名
        if(!$this->chkXcxSignature(['rawData'=>$post['rawData'],'session_key'=>$session_key,'signature'=>$post['signature']]))
        {

            return ['error'=>1,"msg"=>"签名错误"];
        }
        //数据解密
        if(!$data = $this->xcxEncDecode(array_merge($post,['session_key'=>$session_key])))
        {

            return ['error'=>1, "msg"=>"数据解密错误"];
        }
        $data = json_decode($data,true);
        $data['headImgUrl'] = $data['avatarUrl'];
        $data['unionId'] = !isset($data['unionId']) ? "" : $data['unionId'];
        $WxUserModel = new WxUser($this->modelDefaultParam());
        $UserModel  = new Users($this->modelDefaultParam());
        //查询这个用户是否存在
        if(!$info = $WxUserModel->info(['openId'=>$data['openId'],'unionId'=>$data['unionId']]))
        {
            //新增一个微信用户
            $data = $WxUserModel->add($data);
            //新增一个普通用户
            $loginMsg = $this->yklogin();
            //更新微信对应的普通用户id
            $WxUserModel->updateUser(['id'=>$data['id'],'user_id'=>$loginMsg['client_id'],]);

            return [
                'enc_client_id' => $this->EncUserid($loginMsg['client_id']),
                'token'         => $loginMsg['token'],
                'is_kf'         => $loginMsg['is_kf'],
                'nickname'      => $loginMsg['nickname']
            ];

        }

        //更新普通用户的token
        $userInfo = $UserModel->user_info(['client_id'=>$info['user_id']]);
        $token = $UserModel->resetEncString($userInfo);
        $userInfo = [
                'enc_client_id' => $this->EncUserid($userInfo['client_id']),
                'token'         => $token,
                'is_kf'         => $userInfo['is_kf'],
                'nickname'      => $userInfo['nickname']
            ];

        //返回登录token
        return $userInfo;
    }



    //小程序登录凭证验证
    public function chkXcxLogin()
    {

    }

    //获取sessionkey
    private function getSessionKey($code)
    {
        $wxHelp = new wxHelper();
        $config = [
            'appid' => config('xcx.appid'),
            'secret'=>config('xcx.appsecrect'),
            'js_code'=> $code,
            'grant_type'=>'authorization_code'
        ];
        $result     = $wxHelp->httpGet("https://api.weixin.qq.com/sns/jscode2session?".http_build_query($config));
        $result     = json_decode($result, true);

        return isset($result['session_key']) ? $result['session_key'] : false;
    }

    //小程序验证签名
    private function chkXcxSignature($args)
    {
        /**
         * 参数说明
         * args.rawData
         * args.session_key
         * args.signature
         */
        $signature1 = sha1($args['rawData'] . $args['session_key']);
        return $args['signature'] == $signature1;
    }

    //小程序数据解密
    private function xcxEncDecode($args)
    {
        /**
         * 参数说明
         * args.session_key
         * args.encryptedData
         * args.iv
         */

        $appid = config('xcx.appid');
        $sessionKey = $args['session_key'];
        $encryptedData=$args['encryptedData'];
        $iv = $args['iv'];
        $arr = ['appid'=>$appid,'sessionkey'=>$sessionKey,'encrypt'=>$encryptedData,'iv'=>$iv];
        $pc = new WXBizDataCrypt($appid, $sessionKey);

        $errCode = $pc->decryptData($encryptedData, $iv, $data );
        return $errCode == 0 ? $data : false;
    }

    //关键字自动回复
    private function keywordAutoReply($args)
    {
        /**
         * args参数说明
         * args.f_client_id
         * args.to_client_id
         * args.keyword
         */
        $args['keyword'] = strip_tags($args['keyword']);
        $ReplyModel = new KfReply();
        $data = $ReplyModel->info(['keywords'=>$args['keyword']]);

        if(empty($data)) return;
        $userModel = new Users();
        $ToClient = $userModel->user_info(['enc_client_id'=>$args['to_client_id']]);
        if(!empty($data))
        {
            //把对话方式对换
            $args['to_client_id'] = $args['f_client_id'];

            $data['content'] = urldecode($data['content']);
            $args['type'] = 'text';
            $args['msg'] = "
                问题：<span style='color:#0099ff'>{$data['title']} </span><br>
                {$data['content']}
            ";
            $userModel  = new Client(['user_id'=>$ToClient['client_id'],'user_name'=>$ToClient['nickname'],'nickname'=>$ToClient['nickname'],'isKf'=>$ToClient['is_kf']]);
            $userModel->send_text($args);
        }
    }

    //自动回复请求
    public function autoReply()
    {

        /**
         * 参数说明
         * post type text 为文本消息 photo 为图片消息
         * post type data 对应消息类型的内容
         * post to_client_id 对方的enc_client_id
         * post f_client_id  enc_client_id
         * post token
         * return {error,msg}
         */
        if(!$this->check_login())
        {
            return ['error'=>300,"msg"=>"未登录"];
        }

        $post       = input('post.');
        $post       = postJsonToArray();
        //数据验证
        if(!isset($post['f_client_id'])
            || !isset($post['to_client_id'])
        )
        {
            return ['error'=>1,'error'=>'错误'];
        }

        $ReplyModel = new KfReply();
        $data = $ReplyModel->info(['id'=>$post['id']]);
        $userModel = new Users();
        $ToClient = $userModel->user_info(['enc_client_id'=>$post['to_client_id']]);
        if(!empty($data))
        {
            //把对话方式对换
            $post['to_client_id'] = $post['f_client_id'];

            $data['content'] = urldecode($data['content']);
            $post['type'] = 'text';
            $post['msg'] = "
                问题：<span style='color:#0099ff'>{$data['title']} </span><br>
                {$data['content']}
            ";
            $userModel  = new Client(['user_id'=>$ToClient['client_id'],'user_name'=>$ToClient['nickname'],'nickname'=>$ToClient['nickname'],'isKf'=>$ToClient['is_kf']]);
            $result     = $userModel->send_text($post);
        }
        return $result;
    }

}